# -*- encoding:utf-8 -*-
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *

import pygst
pygst.require('0.10')
import gst
import gobject

import ui_playerwidget
import recorder
import asxparser
import config

bbcworldservice='http://www.bbc.co.uk/worldservice/meta/tx/nb/live_infent_au_nb.asx'

def format_time(seconds, use_hours=0):
    if seconds is None or seconds < 0:
        if use_hours: return '--:--:--'
        else:         return '--:--'
    else:
        seconds = int(seconds)
        minutes = seconds / 60
        seconds = seconds % 60
        if use_hours:
            hours = minutes / 60
            minutes = minutes % 60
	    if hours>0 and hours<10:
		return '%02i:%02i:%02i' % (hours, minutes, seconds)
	    else:
		return '%02i:%02i' % (minutes, seconds)
        else:
            return '%02i:%02i' % (minutes, seconds)
	    
class GstPlayer(object):
    def __init__(self,videowidget):
	self.playing = False
	self.vw=videowidget
	self.vw.player=self
	self.player=gst.element_factory_make('playbin','player')
	vis=gst.element_factory_make(config.getvisual(),'visual')
	
	self.player.set_property('vis-plugin',vis)	
	bus=self.player.get_bus()
	bus.enable_sync_message_emission()
	bus.add_signal_watch()
	bus.connect('sync-message::element',self.on_sync_msg)
	bus.connect('message',self.on_message)
	
    def on_message(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_ERROR:
            err, debug = message.parse_error()
            print "Error: %s" % err, debug
            if self.on_eos:
                self.on_eos()
            self.playing = False
        elif t == gst.MESSAGE_EOS:
            if self.on_eos:
                self.on_eos()
            self.playing = False
	elif t == gst.MESSAGE_TAG:
	    tags=message.parse_tag()
	    for tag in tags.keys():
		print '%s=%s'%(tag,tags[tag])
		if tag=='title':
		    self.vw.setWindowTitle(tags[tag])
    def on_sync_msg(self,bus,msg):
	if msg.structure is None:
	    return
	if msg.structure.get_name()=='prepare-xwindow-id':
	    msg.src.set_xwindow_id(self.vw.winId())
	    #msg.src.set_property('force-aspect-ratio', True)
    def set_location(self, location):
        self.player.set_property('uri', location)
	
    def query_position(self):
        "Returns a (position, duration) tuple"
        try:
            position, format = self.player.query_position(gst.FORMAT_TIME)
        except:
            position = gst.CLOCK_TIME_NONE

        try:
            duration, format = self.player.query_duration(gst.FORMAT_TIME)
        except:
            duration = gst.CLOCK_TIME_NONE

        return (position, duration)
    def seek(self, location):
        """
        @param location: time to seek to, in nanoseconds
        """
        gst.debug("seeking to %r" % location)
        event = gst.event_new_seek(1.0, gst.FORMAT_TIME,
            gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
            gst.SEEK_TYPE_SET, location,
            gst.SEEK_TYPE_NONE, 0)

        res = self.player.send_event(event)
        if res:
            gst.info("setting new stream time to 0")
            self.player.set_new_stream_time(0L)
        else:
            gst.error("seek to %r failed" % location)

    def pause(self):
        gst.info("pausing player")
        self.player.set_state(gst.STATE_PAUSED)
        self.playing = False

    def play(self):
        gst.info("playing player")
        self.player.set_state(gst.STATE_PLAYING)
        self.playing = True
        
    def stop(self):
        self.player.set_state(gst.STATE_NULL)
        gst.info("stopped player")
	self.playing = False
    def get_state(self, timeout=1):
        return self.player.get_state(timeout=timeout)

    def is_playing(self):
        return self.playing
    def record(self,dorecord):
	if dorecord:
	    filename=os.path.split(self.player.get_property('uri'))[-1]
	    savefile=os.path.join(config.getrecpath(),filename)
	    self.player.set_property('audio-sink',recorder.RecorderBin(savefile))
	else:
	    self.player.set_property('audio-sink',gst.element_factory_make('alsasink'))
class VideoWidget(QDialog):
    def __init__(self,parent=None):
	super(QWidget,self).__init__(parent)
	self.player=None
	self.parent=parent
    def closeEvent(self,event):
	self.setVisible(False)
	event.ignore()
    def keyPressEvent(self,keyevent):
	if keyevent.key()==Qt.Key_F:
	    if self.isFullScreen():
		self.showNormal()
	    else:
		self.showFullScreen()
class PlayerWidget(QWidget,ui_playerwidget.Ui_PlayerWidget):
    UPDATE_INTERVAL = 500
    def __init__(self,parent=None):
        super(PlayerWidget,self).__init__(parent)
	self.vw=VideoWidget(self)
	self.vw.show()
	self.setupUi(self)	
	self.player=GstPlayer(self.vw)
	#filelist='file:///media/wind/video.mp4'	
	#self.filelist=['file:///home/shrek/Music/test.mp3',
	#    'file:///home/shrek/Music/西班牙斗牛士.mp3',
	#    ]
	#filelist='http://bgmusic.8dou.net/jjsl/04.mp3'
	#self.filelist=open('/home/shrek/playlist.m3u').read().strip().split('\n')
	self.filelist=asxparser.AsxParser(bbcworldservice).parse()
	self.curr=0
	self.player.set_location(self.filelist[self.curr])
	
	self.seek_timeout_id = -1
	self.update_id = -1
        self.changed_id = -1
	def on_eos():
	    print 'eof'
	    self.player.stop()
	    if self.curr<len(self.filelist)-1:
		self.curr+=1
		self.player.set_location(self.filelist[self.curr])
		self.play_toggled()
        self.player.on_eos = lambda *x: on_eos()
	
	#self.connect(self.hsProgress,SIGNAL('sliderPressed()'),self.on_hsProgress_sliderPressed)
	#self.connect(self.hsProgress,SIGNAL('sliderReleased()'),self.on_hsProgress_sliderReleased)
    def play_toggled(self):
        if self.player.is_playing():
            self.player.pause()
            self.btnPlayPause.setText('>')
        else:
            self.player.play()
	    self.btnPlayPause.setText('||')
            if self.update_id == -1:
                self.update_id = gobject.timeout_add(self.UPDATE_INTERVAL,
                                                     self.update_scale_cb)
    def update_scale_cb(self):
        self.p_position, self.p_duration = self.player.query_position()
        if self.p_position != gst.CLOCK_TIME_NONE:
	    value = self.p_position * 100.0 / self.p_duration
	    self.hsProgress.setSliderPosition(value)
	    self.lProgress.setText(self.format_value(self.p_position))
	if self.player.get_state()[1]==gst.STATE_NULL:
	    self.hsProgress.setSliderPosition(0)
	    self.btnPlayPause.setText('>')
	    self.lProgress.setText('--:--/--:--')
        return True
    def format_value(self,position):
        if self.p_duration == -1:
            realt = 0
        else:
            realt = self.p_duration
	if position == -1:
            real = 0
        else:
            real = position
        
        seconds = real / gst.SECOND
	total= realt / gst.SECOND
        return "%s/%s" % (format_time(seconds,1),format_time(total,1))
    def on_hsProgress_sliderPressed(self):        
        self.was_playing = self.player.is_playing()
        if self.was_playing:
            self.player.pause()
        # don't timeout-update position during seek
        if self.update_id != -1:
            print gobject.source_remove(self.update_id)
            self.update_id = -1
    def on_hsProgress_sliderReleased(self):	
	real = long(self.hsProgress.sliderPosition() * self.p_duration / 100) # in ns
        self.player.seek(real)
        # allow for a preroll
        self.player.get_state(timeout=50*gst.MSECOND) # 50 ms
	if self.was_playing:
	    self.player.play()
        if self.update_id ==-1:
            self.update_id = gobject.timeout_add(self.UPDATE_INTERVAL,
                self.update_scale_cb)
    def on_hsProgress_valueChanged(self):
	if self.update_id!=-1:
	    return # the update process is running, do nothing
	if self.p_duration == -1:
            real = 0
        else:
            real = self.hsProgress.sliderPosition() * self.p_duration / 100

        self.lProgress.setText(self.format_value(real))
	
	
    @pyqtSignature("")
    def on_btnPlayPause_clicked(self):
	#QMessageBox.critical(self,"Please select html source file","No Html source file found")   
	#self.vw.setVisible(True)
	self.play_toggled()
    @pyqtSignature("")
    def on_btnStop_clicked(self):
	#QMessageBox.critical(self,"Please select html source file","No Html source file found")   
	#self.vw.setVisible(False)
	self.player.stop()
	#self.play_toggled()
    @pyqtSignature('')
    def on_btnWindow_clicked(self):
	self.vw.setVisible(not self.vw.isVisible())
    @pyqtSignature('')
    def on_btnPrevious_clicked(self):
	if self.curr>0:
	    self.curr-=1
	    self.player.stop()
	    self.player.set_location(self.filelist[self.curr])
	    self.play_toggled()
    @pyqtSignature('')
    def on_btnNext_clicked(self):
	if self.curr<len(self.filelist)-1:
	    self.curr+=1
	    self.player.stop()
	    self.player.set_location(self.filelist[self.curr])
	    self.play_toggled()
    @pyqtSignature('')
    def on_btnRec_clicked(self):
	if self.player.is_playing():	    
	    self.player.stop()
	    self.player.record(self.btnRec.isChecked())	    
	    self.player.play()
	    self.btnPlayPause.setEnabled(not self.btnRec.isChecked())
	    self.btnStop.setEnabled(not self.btnRec.isChecked())
	    self.btnPrevious.setEnabled(not self.btnRec.isChecked())
	    self.btnNext.setEnabled(not self.btnRec.isChecked())
